home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 June
/
EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso
/
earcd
/
c-lang
/
vbcc.lha
/
vbcc
/
regs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-15
|
37KB
|
869 lines
/* $VER: vbcc (regs.c) V0.3 */
/* Registerzuteilung */
#include "opt.h"
#ifndef NO_OPTIMIZER
int (*savings)[MAXR+1];
int *rvlist;
int cmp_savings(const void *v1,const void *v2)
/* Vergleichsfkt, um rvlist nach savings zu sortieren */
{
return savings[*(int *)v2][0]-savings[*(int *)v1][0];
}
void insert_regs(struct flowgraph *fg1)
/* soll mal die blockweise Registervariablenzuteilung einfuegen, im */
/* Moment macht es nur Ausgaben */
{
int i;struct IC *p,*lic=0,*new;struct flowgraph *lfg=0,*fg;
if(DEBUG&1024) printf("inserting register variables\n");
fg=fg1;
while(fg){
if(DEBUG&2048) printf("block %d:\n",fg->index);
p=fg->start;
while(p){
for(i=1;i<=MAXR;i++){
if(!fg->regv[i]) continue;
if(p->code==ALLOCREG&&p->q1.reg==i) ierror(0);
if((p->q1.flags&(VAR|DONTREGISTERIZE))==VAR&&p->q1.v==fg->regv[i]){
p->q1.flags|=REG;
p->q1.reg=i;
}
if((p->q2.flags&(VAR|DONTREGISTERIZE))==VAR&&p->q2.v==fg->regv[i]){
p->q2.flags|=REG;
p->q2.reg=i;
}
if((p->z.flags&(VAR|DONTREGISTERIZE))==VAR&&p->z.v==fg->regv[i]){
p->z.flags|=REG;
p->z.reg=i;
}
}
if(p==fg->end) break;
p=p->next;
}
if(fg->start&&fg->start->code==LABEL) lic=fg->start;
for(i=1;i<=MAXR;i++){
if(fg->regv[i]){
if(DEBUG&2048) printf("(%s),%d assigned to %s\n",fg->regv[i]->identifier,fg->regv[i]->offset,regnames[i]);
if(BTST(fg->av_in,fg->regv[i]->index)){
/* Variable beim Eintritt aktiv? */
struct flowlist *lp;int flag;
lp=fg->in;flag=0;
/* Parameter am Anfang laden? */
if(fg==fg1&&fg->regv[i]->offset<0) flag=1;
while(lp){
if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]&&BTST(lp->graph->av_out,fg->regv[i]->index)){ flag=1;break; }
lp=lp->next;
}
if(flag){
if(DEBUG&2048) printf("\thave to load it at start of block\n");
new=mymalloc(ICS);
new->code=ASSIGN;
new->typf=fg->regv[i]->vtyp->flags;
new->q1.flags=VAR|DONTREGISTERIZE;
new->q1.val.vlong=l2zl(0L);
new->q1.v=fg->regv[i];
new->q2.flags=0;
new->q2.reg=szof(fg->regv[i]->vtyp);
new->z.flags=VAR|REG;
new->z.val.vlong=l2zl(0L);
new->z.v=fg->regv[i];
new->z.reg=i;
new->q1.am=new->q2.am=new->z.am=0;
insert_IC_fg(fg,lic,new);
}
}
if(BTST(fg->av_out,fg->regv[i]->index)){
/* Variable beim Austritt aktiv? */
struct flowlist *lp;int flag=0;
/* Wert muss gespeichert werden, falls ein Vorgaenger */
/* eines Nachfolgers den Wert nicht im selben Register */
if((fg->normalout&&(!fg->normalout->end||fg->normalout->end->code!=BRA))&&BTST(fg->normalout->av_in,fg->regv[i]->index)){
if(fg->normalout->regv[i]!=fg->regv[i]) flag=1;
lp=fg->normalout->in;
while(!flag&&lp){
if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]){ flag=1; break; }
lp=lp->next;
}
}
if(!flag&&fg->branchout&&BTST(fg->branchout->av_in,fg->regv[i]->index)){
if(fg->branchout->regv[i]!=fg->regv[i]) flag=1;
lp=fg->branchout->in;
while(!flag&&lp){
if(lp->graph&&lp->graph->regv[i]!=fg->regv[i]){ flag=1; break; }
lp=lp->next;
}
}
if(flag){
struct IC *tp;
if(DEBUG&2048) printf("\thave to save it at end of block\n");
new=mymalloc(ICS);
new->code=ASSIGN;
new->typf=fg->regv[i]->vtyp->flags;
new->q1.flags=VAR|REG;
new->q1.val.vlong=l2zl(0L);
new->q1.v=fg->regv[i];
new->q1.reg=i;
new->q2.flags=0;
new->q2.reg=szof(fg->regv[i]->vtyp);
new->z.flags=VAR|DONTREGISTERIZE;
new->z.val.vlong=l2zl(0L);
new->z.v=fg->regv[i];
new->q1.am=new->q2.am=new->z.am=0;
/* Vor FREEREGs und evtl. Branch+COMPARE/TEST setzen */
if(fg->end){
tp=fg->end;
while(tp!=fg->start&&tp->code==FREEREG)
tp=tp->prev;
if(tp&&tp->code>=BEQ&&tp->code<=BRA){
if(tp->code<BRA){
int c;
do{
tp=tp->prev;
c=tp->code;
if(c!=FREEREG&&c!=COMPARE&&c!=TEST) ierror(0);
}while(c!=COMPARE&&c!=TEST);
}
tp=tp->prev;
}
}else tp=lic;
insert_IC_fg(fg,tp,new);
}
}
if(!lfg||!lfg->regv[i]) insert_allocreg(fg,lic,ALLOCREG,i);
if(!fg->normalout||!fg->normalout->regv[i])
insert_allocreg(fg,fg->end?fg->end:lic,FREEREG,i);
}
}
if(fg->end) lic=fg->end;
lfg=fg;
fg=fg->normalout;
}
}
void do_loop_regs(struct flowgraph *start,struct flowgraph *end)
/* macht die Variablenzuweisung in Schleife start-end */
{
struct flowgraph *g,*e;
int i,r,is_loop,flag;
struct Var *lregs[MAXR+1]={0};
unsigned char rused[(MAXR+CHAR_BIT)/CHAR_BIT];
if(start->loopend){
is_loop=1;
if(start!=end){
g=start->normalout;
while(g&&g!=end){
e=g->loopend;
if(e){
do_loop_regs(g,e);
g=e;
}
g=g->normalout;
}
}
}else{
is_loop=0;
if(DEBUG&1024) printf("global register allocation\n");
}
if(DEBUG&1024) printf("assigning regs to blocks %d to %d\n",start->index,end->index);
/* berechnen, wieviel ungefaehr eingespart wird, wenn eine Variable */
/* fuer diese Schleife in einem best. Register gehalten wird */
if(DEBUG&1024) printf("calculating approximate savings\n");
/* alle auf 0 */
for(i=0;i<vcount-rcount;i++){
for(r=1;r<=MAXR;r++){
savings[i][r]=0;
if(!is_loop){
if(vilist[i]->offset<0&&(vilist[i]->storage_class==REGISTER||vilist[i]->storage_class==AUTO))
savings[i][r]=-1;
}
}
}
g=start;
while(g){
struct IC *p;struct Var *v;
int t,vt;
e=g->loopend;
if(e&&g!=start){
/* innere Schleifen schon erledigt; nur noch schauen, ob Variablen */
/* in denselben Registern verbleiben */
/* innere Schleife ueberspringen - nur noch zaehlen, wie oft */
/* jedes Register von temporaeren Variablen belegt ist; wie */
/* viel das ausmacht, kann aber nur geschaetzt werden */
while(g&&g!=e->normalout){
for(r=1;r<=MAXR;r++){
if(g->regv[r]){
if(DEBUG&2048) printf("inner loop has (%s),%d assigned to %s\n",g->regv[r]->identifier,g->regv[r]->offset,regnames[r]);
if(BTST(g->av_in,g->regv[r]->index)) savings[g->regv[r]->index][r]++;
if(BTST(g->av_out,g->regv[r]->index)) savings[g->regv[r]->index][r]++;
/* falls Variable schon in anderem Register */
for(i=1;i<=MAXR;i++)
if(i!=r) savings[g->regv[r]->index][i]-=2;
}
if(BTST(g->regused,r)){
int v;
if(g->regv[r]) v=g->regv[r]->index; else v=-1;
for(i=0;i<vcount-rcount;i++){
if(BTST(g->av_in,i)&&i!=v) savings[i][r]-=2;
if(BTST(g->av_out,i)&&i!=v) savings[i][r]-=2;
}
}else if(regscratch[r]&&g->calls>0){
for(i=0;i<vcount-rcount;i++) savings[i][r]-=g->calls*2;
}
}
g=g->normalout;
}
continue;
}
if(g->calls>0){
/* bei Funktionsaufrufen muessen Scratchregister gespeichert werden */
for(r=1;r<=MAXR;r++)
if(regscratch[r])
for(i=0;i<vcount-rcount;i++) savings[i][r]-=g->calls*2;
}
/* Wenn das Register in dem Block benutzt wird, muss man es retten */
for(r=1;r<=MAXR;r++){
if(BTST(g->regused,r)){
int vi;
if(g->regv[r]) vi=g->regv[r]->index; else vi=-1;
for(i=0;i<vcount-rcount;i++)
if(vi!=i) savings[i][r]-=2;
}
}
p=g->start;
while(p){
if((p->q1.flags&(VAR|VARADR|REG))==VAR){
v=p->q1.v;
if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
vt=v->vtyp->flags&31;
i=v->index;
if(p->q1.flags&DREFOBJ) t=p->typf&31; else t=0;
flag=0;
if(!is_loop){
/* schauen, ob Variable schon in einem Register */
for(r=1;r<=MAXR;r++) if(g->regv[r]==v) {flag=1;break;}
}
if(!flag){
for(r=1;r<=MAXR;r++){
if(!regsa[r]&&!BTST(g->regused,r)){
/* extra saving, falls passendes Reg fuer DREF */
if(t&®ok(r,vt,t)) savings[i][r]++;
if(regok(r,vt,0)) savings[i][r]++;
}
}
}
}
}
if((p->q2.flags&(VAR|VARADR|REG))==VAR){
v=p->q2.v;
if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
vt=v->vtyp->flags&31;
i=v->index;
if(p->q2.flags&DREFOBJ) t=p->typf&31; else t=0;
flag=0;
if(!is_loop){
/* schauen, ob Variable schon in einem Register */
for(r=1;r<=MAXR;r++) if(g->regv[r]==v) {flag=1;break;}
}
if(!flag){
for(r=1;r<=MAXR;r++){
if(!regsa[r]&&!BTST(g->regused,r)){
/* extra saving, falls passendes Reg fuer DREF */
if(t&®ok(r,vt,t)) savings[i][r]++;
if(regok(r,vt,0)) savings[i][r]++;
}
}
}
}
}
if((p->z.flags&(VAR|VARADR|REG))==VAR){
v=p->z.v;
if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
vt=v->vtyp->flags&31;
i=v->index;
if(p->z.flags&DREFOBJ) t=p->typf&31; else t=0;
flag=0;
if(!is_loop){
/* schauen, ob Variable schon in einem Register */
for(r=1;r<=MAXR;r++) if(g->regv[r]==v) {flag=1;break;}
}
if(!flag){
for(r=1;r<=MAXR;r++){
if(!regsa[r]&&!BTST(g->regused,r)){
/* extra saving, falls passendes Reg fuer DREF */
if(t&®ok(r,vt,t)) savings[i][r]++;
if(regok(r,vt,0)) savings[i][r]++;
}
}
}
}
}
if(p==g->end) break;
p=p->next;
}
if(g==end) break;
g=g->normalout;
}
/* Maximum ermitteln */
for(i=0;i<vcount-rcount;i++){
int m=0;
for(r=1;r<=MAXR;r++){
if(savings[i][r]>m) m=savings[i][r];
}
savings[i][0]=m;
}
if(DEBUG&2048){
for(i=0;i<vcount-rcount;i++){
printf("(%s),%d(best=%d):\n",vilist[i]->identifier,vilist[i]->offset,savings[i][0]);
for(r=1;r<=MAXR;r++)
printf("%s=%d ",regnames[r],savings[i][r]);
printf("\n");
}
}
/* Suchen, welche Variablen/Registerkombination das beste Ergebnis */
/* liefert. Nur angenaehert, da sonst wohl zu aufwendig. Simplex? */
memset(rused,0,(MAXR+CHAR_BIT)/CHAR_BIT);
for(i=0;i<vcount-rcount;i++) rvlist[i]=i;
qsort(rvlist,vcount-rcount,sizeof(*rvlist),cmp_savings);
for(i=0;i<vcount-rcount;i++){
int use,m=0,vi;
vi=rvlist[i];
if(DEBUG&2048) printf("%d: (%s),%d(best=%d)\n",i,vilist[vi]->identifier,vilist[vi]->offset,savings[vi][0]);
for(r=1;r<=MAXR;r++){
if(!lregs[r]&&savings[vi][r]>m){
m=savings[vi][r];
use=r;
if(m==savings[vi][0]) break;
}
}
if(m>0){
if(DEBUG&1024) printf("assigned (%s),%d to %s, saving=%d\n",vilist[vi]->identifier,vilist[vi]->offset,regnames[use],m);
lregs[use]=vilist[vi];
BSET(rused,use);
}
}
/* Registervariablen in alle Bloecke der Schleife eintragen */
/* dabei beruecksichtigen, dass sie in manchen Bloecken nicht */
/* in Register kommen koennen, wenn das Register da schon von */
/* local_regs benutzt wird */
if(DEBUG&1024) printf("propagate register vars\n");
g=start;
while(g){
for(r=1;r<=MAXR;r++){
if(lregs[r]&&!BTST(g->regused,r)){
int flag=0;
if(g->regv[r]) ierror(0);
/* Variable schon in anderem Register? */
for(i=1;i<=MAXR;i++){
if(i!=r&&g->regv[i]==lregs[r]){flag=1;break;}
}
if(!flag){
g->regv[r]=lregs[r];
BSET(g->regused,r);
}
}
}
if(g==end) break;
g=g->normalout;
}
if(is_loop){
/* in Schleifenvorkopf eintragen */
if(start->in->graph->index>=0) ierror(0);
memcpy(&start->in->graph->regv,&start->regv,sizeof(start->regv));
memcpy(&start->in->graph->regused,rused,sizeof(rused));
/* in Schleifenfuss eintragen */
if(end->normalout->index>=0) ierror(0);
memcpy(&end->normalout->regv,&start->regv,sizeof(start->regv));
memcpy(&end->normalout->regused,rused,sizeof(rused));
}
#if 0
/* in start ausbessern, wenn einige Register belegt sind */
for(r=1;r<=MAXR;r++)
if(BTST(start->regused,r)) start->regv[r]=0;
bvunite(start->regused,rused,(MAXR+CHAR_BIT)/CHAR_BIT);
#endif
}
void block_regs(struct flowgraph *fg)
/* macht die Variablenzuweisung fuer einzelne Bloecke */
{
struct flowgraph *g,**fgp;
int i,r,changed,fgz;
if(DEBUG&1024) printf("block_regs\n");
savings=mymalloc((vcount-rcount)*sizeof(*savings));
rvlist=mymalloc((vcount-rcount)*sizeof(*rvlist));
/* Array auf Bloecke im Flussgraphen mangels doppelter Verkettung */
fgp=mymalloc(basic_blocks*sizeof(*fgp));
g=fg;fgz=0;
while(g){
fgp[fgz]=g;fgz++;
g=g->normalout;
}
if(fgz>basic_blocks) ierror(0); else basic_blocks=fgz;
/* alle auf 0 */
do{
changed=0;
if(DEBUG&1024) printf("block_regs pass\n");
for(fgz=basic_blocks-1;fgz>=0;fgz--){
struct IC *p;struct Var *v;struct flowlist *lp;
int t,vt;
g=fgp[fgz];
if(DEBUG&2048) printf("assigning regs to block %d\n",g->index);
/* berechnen, wieviel ungefaehr eingespart wird, wenn eine Variable */
/* fuer diesen Block in einem best. Register gehalten wird */
if(DEBUG&2048) printf("calculating approximate savings\n");
for(i=0;i<vcount-rcount;i++){
for(r=1;r<=MAXR;r++){
if(!g->regv[r]||g->regv[r]->index!=i){
int w=0;
/* Variable muss evtl. geladen/gespeichert werden */
if(BTST(g->av_in,i)) w--;
if(BTST(g->av_out,i)) w--;
savings[i][r]=w;
}
}
}
if(g->calls>0){
/* bei Funktionsaufrufen muessen Scratchregister gespeichert werden */
for(r=1;r<=MAXR;r++)
if(regscratch[r])
for(i=0;i<vcount-rcount;i++) savings[i][r]-=g->calls*2;
}
/* Wenn Vorgaenger/Nachfolger selbe Variable im selben */
/* Register hat, entfaellt Laden/Speichern in diesem */
/* Block und vermutlich auch im Vorgaenger/Nachfolger */
/* nicht immer, aber naeherungsweise... */
lp=g->in;
while(lp){
if(lp->graph){
for(r=1;r<=MAXR;r++){
if(lp->graph->regv[r]&&BTST(g->av_in,lp->graph->regv[r]->index)) savings[lp->graph->regv[r]->index][r]+=2;
}
}
lp=lp->next;
}
if(g->branchout){
for(r=1;r<=MAXR;r++){
if(g->branchout->regv[r]&&BTST(g->av_out,g->branchout->regv[r]->index)) savings[g->branchout->regv[r]->index][r]+=2;
}
}
if(g->normalout&&(!g->normalout->end||g->normalout->end->code!=BRA)){
for(r=1;r<=MAXR;r++){
if(g->normalout->regv[r]&&BTST(g->av_out,g->normalout->regv[r]->index)) savings[g->normalout->regv[r]->index][r]+=2;
}
}
p=g->start;
while(p){
if((p->q1.flags&(VAR|VARADR|REG))==VAR){
v=p->q1.v;
if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
vt=v->vtyp->flags&31;
i=v->index;
if(p->q1.flags&DREFOBJ) t=p->typf&31; else t=0;
for(r=1;r<=MAXR;r++){
if(!regsa[r]&&!BTST(g->regused,r)){
/* extra saving, falls passendes Reg fuer DREF */
if(t&®ok(r,vt,t)) savings[i][r]++;
if(regok(r,vt,0)) savings[i][r]++;
}
}
}
}
if((p->q2.flags&(VAR|VARADR|REG))==VAR){
v=p->q2.v;
if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
vt=v->vtyp->flags&31;
i=v->index;
if(p->q2.flags&DREFOBJ) t=p->typf&31; else t=0;
for(r=1;r<=MAXR;r++){
if(!regsa[r]&&!BTST(g->regused,r)){
/* extra saving, falls passendes Reg fuer DREF */
if(t&®ok(r,vt,t)) savings[i][r]++;
if(regok(r,vt,0)) savings[i][r]++;
}
}
}
}
if((p->z.flags&(VAR|VARADR|REG))==VAR){
v=p->z.v;
if((v->storage_class==AUTO||v->storage_class==REGISTER)&&!(v->flags&USEDASADR)){
vt=v->vtyp->flags&31;
i=v->index;
if(p->z.flags&DREFOBJ) t=p->typf&31; else t=0;
for(r=1;r<=MAXR;r++){
if(!regsa[r]&&!BTST(g->regused,r)){
/* extra saving, falls passendes Reg fuer DREF */
if(t&®ok(r,vt,t)) savings[i][r]++;
if(regok(r,vt,0)) savings[i][r]++;
}
}
}
}
if(p==g->end) break;
p=p->next;
}
/* moegliche Kandidaten suchen; muss nicht immer die beste */
/* Kombination finden, sollte aber bei lokaler Vergabe */
/* selten einen Unterschied machen */
for(r=1;r<=MAXR;r++){
if(g->regv[r]||BTST(g->regused,r)) continue;
for(i=0;i<vcount-rcount;i++){
if(savings[i][r]>0){
int flag;struct Var *v=vilist[i];
/* Variable schon in anderem Register? */
for(flag=1;flag<=MAXR;flag++)
if(g->regv[flag]==v){flag=-1;break;}
if(flag>0){
if(DEBUG&1024) printf("assigned (%s),%d to %s; saving=%d\n",vilist[i]->identifier,vilist[i]->offset,regnames[r],savings[i][r]);
g->regv[r]=vilist[i];
BSET(g->regused,r);
changed=1;
break;
}
}
}
}
}
}while(changed);
/* jetzt nochmal globale Register vergeben */
/* do_loop_regs(fgp[0],fgp[basic_blocks-1]);*/
free(fgp);
free(rvlist);
free(savings);
}
void loop_regs(struct flowgraph *fg)
/* weist Variablen in Schleifen Register zu */
{
struct flowgraph *g,*first=fg;
if(DEBUG&1024) printf("assigning regs in loops\n");
savings=mymalloc((vcount-rcount)*sizeof(*savings));
rvlist=mymalloc((vcount-rcount)*sizeof(*rvlist));
while(fg){
g=fg->loopend;
if(g){
do_loop_regs(fg,g);
fg=g;
}
if(!fg->normalout){
/* jetzt nochmal global Register vergeben */
do_loop_regs(first,fg);
}
fg=fg->normalout;
}
free(rvlist);
free(savings);
}
void insert_allocreg(struct flowgraph *fg,struct IC *p,int code,int reg)
/* fuegt ein ALLOCREG/FREEREG (in code) hinter p ein - bei p==0 in */
/* first_ic */
{
struct IC *new=mymalloc(ICS);
BSET(fg->regused,reg);
regused[reg]=1;
new->code=code;
new->typf=0;
new->q1.am=new->q2.am=new->z.am=0;
new->q1.flags=REG;
new->q1.reg=reg;
new->q2.flags=new->z.flags=0;
insert_IC_fg(fg,p,new);
}
struct Var *lregv[MAXR+1];
struct flowgraph *lfg;
int replace_local_reg(struct obj *o)
/* tested, ob o eine Scratch-Variable ist und ersetzt sie gegebenenfalls */
{
unsigned int i;struct Var *v;
if((o->flags&(VAR|REG|VARADR))==VAR){
v=o->v;i=v->index;
if(BTST(lfg->av_kill,i)&&!BTST(lfg->av_out,i)){
for(i=1;i<=MAXR;i++){
if(lregv[i]==v){
o->flags|=(REG|SCRATCH);
/* o->flags&=~VAR;*/
o->reg=i;
return(i);
}
}
}
}
return(0);
}
void local_regs(struct flowgraph *fg)
/* versucht Variablen, die nur innerhalb eines Basic Blocks benutzt */
/* werden (kill==true und out==false), Register zuzuweisen. */
{
struct IC *p; struct Var *v;
int i,t,r,nr,mustalloc,regu[MAXR+1];
if(DEBUG&1024) printf("assigning temporary variables to registers\n");
lfg=fg;
while(lfg){
for(i=1;i<=MAXR;i++){ lregv[i]=0; regu[i]=regsa[i]; lfg->regv[i]=0;}
memset(&lfg->regused,0,(MAXR+CHAR_BIT)/CHAR_BIT);
lfg->calls=0;
p=lfg->end;
while(p){
i=replace_local_reg(&p->z);
if(i&&!(p->z.flags&DREFOBJ)){
lregv[i]=0;regu[i]--;
nr=i;mustalloc=1;
if(DEBUG&2048) printf("regu[%s] decremented to %d\n",regnames[i],regu[i]);
}else nr=0;
if(p->code!=ADDRESS){
if(replace_local_reg(&p->q1)==nr) mustalloc=0;
if(replace_local_reg(&p->q2)==nr) mustalloc=0;
}
/* hier wegen USEQ2ASZ aufpassen; kommutative ICs sollten so */
/* angeordnet werden, dass ein evtl. Register rechts steht */
if((p->q2.flags&(VAR|REG|VARADR))==VAR&&!(p->q2.v->flags&USEDASADR)&&!(p->q2.v->vtyp->flags&VOLATILE)&&(p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER)){
i=p->q2.v->index;
if(BTST(lfg->av_kill,i)&&!BTST(lfg->av_out,i)){
t=p->q2.v->vtyp->flags;
if(USEQ2ASZ&&nr&®ok(nr,t,0)&&(!(p->q2.flags&DREFOBJ)||regok(nr,t,p->typf))) r=nr; else r=0;
for(i=0;r==0&&i<=MAXR;i++){
if(!regu[i]&&!regsa[i]&®ok(i,t,0)&&(USEQ2ASZ||i!=nr)) {r=i;break;}
}
if(r){
if(r!=nr) insert_allocreg(lfg,p,FREEREG,r);
else mustalloc=0;
lregv[r]=p->q2.v;regused[r]=regu[r]=1;
if(replace_local_reg(&p->q2)!=r) ierror(0);
replace_local_reg(&p->q1);
replace_local_reg(&p->z);
if((DEBUG&1024)&&*p->q2.v->identifier) printf("temporary <%s> assigned to %s\n",p->q2.v->identifier,regnames[r]);
if(DEBUG&2048) printf("temporary <%s> assigned to %s\n",p->q2.v->identifier,regnames[r]);
}
}
}
if((p->z.flags&(VAR|REG|DREFOBJ))==(VAR|DREFOBJ)&&!(p->z.v->flags&USEDASADR)&&!(p->z.v->vtyp->flags&VOLATILE)&&(p->z.v->storage_class==AUTO||p->z.v->storage_class==REGISTER)){
i=p->z.v->index;
if(BTST(lfg->av_kill,i)&&!BTST(lfg->av_out,i)){
for(r=0,i=0,t=p->z.v->vtyp->flags;i<=MAXR;i++){
if(!regu[i]&&!regsa[i]&®ok(i,t,0)) {r=i;break;}
}
if(r){
insert_allocreg(lfg,p,FREEREG,r);
lregv[r]=p->z.v;regused[r]=regu[r]=1;
if(replace_local_reg(&p->z)!=r){
for(i=1;i<=MAXR;i++) if(lregv[i]) printf("%d:%s=%s(%p)\n",i,regnames[i],lregv[i]->identifier,lregv[i]);
ierror(r);}
replace_local_reg(&p->q1);
if((DEBUG&1024)&&*p->z.v->identifier) printf("temporary <%s> assigned to %s\n",p->z.v->identifier,regnames[r]);
if(DEBUG&2048) printf("temporary <%s> assigned to %s\n",p->z.v->identifier,regnames[r]);
}
}
}
if((p->q1.flags&(VAR|REG|VARADR))==VAR&&!(p->q1.v->flags&USEDASADR)&&!(p->q1.v->vtyp->flags&VOLATILE)&&(p->q1.v->storage_class==AUTO||p->q1.v->storage_class==REGISTER)){
i=p->q1.v->index;
if(BTST(lfg->av_kill,i)&&!BTST(lfg->av_out,i)){
t=p->q1.v->vtyp->flags;
if(nr&®ok(nr,t,0)&&(!(p->q1.flags&DREFOBJ)||regok(nr,t,p->typf))) r=nr; else r=0;
for(i=0;r==0&&i<=MAXR;i++){
if(!regu[i]&&!regsa[i]&®ok(i,t,0)) {r=i;break;}
}
if(r){
if(r!=nr) insert_allocreg(lfg,p,FREEREG,r);
else mustalloc=0;
lregv[r]=p->q1.v;regused[r]=regu[r]=1;
if(replace_local_reg(&p->q1)!=r) ierror(0);
if((DEBUG&1024)&&*p->q1.v->identifier) printf("temporary <%s> assigned to %s\n",p->q1.v->identifier,regnames[r]);
if(DEBUG&2048) printf("temporary <%s> assigned to %s\n",p->q1.v->identifier,regnames[r]);
}
}
}
if(p->code==CALL){
lfg->calls++;
/* falls Scratchregister bei Funktionsaufruf benutzt */
/* wird, moeglichst auf ein anderes ausweichen */
for(i=1;i<=MAXR;i++){
if(lregv[i]&®scratch[i]){
int r;
for(r=1;r<=MAXR;r++){
if(!lregv[r]&&!regscratch[r]&®ok(r,lregv[i]->vtyp->flags,0)){
/* noch schauen, ob es benutzt wurde */
struct IC *ip=p;int flag=0;
while(!(ip->code==FREEREG&&ip->q1.reg==i)){
if(ip->code==ALLOCREG&&ip->q1.reg==r){flag=1;break;}
ip=ip->next;
}
if(flag) continue;
do{
if((ip->q1.flags®)&&ip->q1.reg==i) ip->q1.reg=r;
if((ip->q2.flags®)&&ip->q2.reg==i) ip->q2.reg=r;
if((ip->z.flags®)&&ip->z.reg==i) ip->z.reg=r;
ip=ip->prev;
}while(ip!=p->prev);
lregv[r]=lregv[i];
BSET(lfg->regused,r);
regused[r]=regu[r]=1;
lregv[i]=0;regu[i]=0;
break;
}
}
}
}
}
/* die Faelle beachten, wenn schon im IC ein Register */
/* angesprochen wird (sollte nur bei CALL und return auftreten */
if(p->code==FREEREG){
ierror(0);
if(regu[p->q1.reg]) remove_IC_fg(lfg,p);
regu[p->q1.reg]++;
}
if(p->code==ALLOCREG){
ierror(0);
if(regu[p->q1.reg]==2) remove_IC_fg(lfg,p);
regu[p->q1.reg]--;
}
if(p==lfg->start) i=1; else i=0;;
p=p->prev;
if(nr&&mustalloc) insert_allocreg(lfg,p,ALLOCREG,nr);
if(i) break;
}
lfg=lfg->normalout;
}
}
void insert_saves(void)
/* fuegt speichern von Registern bei Funktionsaufrufen ein */
{
int i,c;struct IC *p;
if(DEBUG&1024) printf("insert_saves\n");
for(i=1;i<=MAXR;i++) regs[i]=regsa[i];
for(p=first_ic;p;p=p->next){
c=p->code;
if(c==ALLOCREG) regs[p->q1.reg]=1;
if(c==FREEREG) regs[p->q1.reg]=0;
if(c==CALL){
struct IC *s;
/* das Wiederherstellen nach dem GETRETURN */
s=p;
if(s->next&&s->next->code==FREEREG) {s=s->next;regs[s->q1.reg]=0;}
if(s->next&&s->next->code==GETRETURN) s=s->next;
if(s->next&&s->next->code==ALLOCREG&&s->next->next&&s->next->next->code==GETRETURN) s=s->next->next;
savescratch(MOVEFROMREG,p->prev,0);
savescratch(MOVETOREG,s,0);
}
}
}
#endif
void simple_regs(void)
/* haelt Variablen in Registern, simple Version */
{
int i2,i,j;int pri;struct Var *v;
struct IC *icp,*start=first_ic;
if(!first_ic) return;
for(i2=0;i2<=MAXR*4;i2++){
int only_best,pointertype;
if(i2<=MAXR*2){i=i2;only_best=1;} else {i=i2/2;pointertype=only_best=0;}
if(i>MAXR){
i-=MAXR;
if(regsv[i]) continue;
}else{
regsv[i]=0;
/* Ziehe Scratchregister vor, wenn kein Funktionsaufruf */
/* erfolgt, sonst erst andere */
if(!function_calls&&!regscratch[i]) continue;
if(function_calls&®scratch[i]) continue;
}
if(regused[i]) continue;
/* Nicht-Scratchregister muessen einmal gesichert und wieder */
/* hergestellt werden, Scratchregister bei jedem Call */
if(regscratch[i]) pri=function_calls*2; else /*pri=2;*/ pri=0;
for(j=0;j<=1;j++){
if(j==0) v=merk_varf; else v=first_var[1];
while(v){
if(v->storage_class==AUTO||v->storage_class==REGISTER){
if(!(v->flags&USEDASADR)&&!(v->vtyp->flags&VOLATILE)){
if(only_best&&v->vtyp->next) pointertype=v->vtyp->next->flags;
if(v->priority>pri&®ok(i,v->vtyp->flags&31,pointertype)){
regsv[i]=v;pri=v->priority;
}
}
}
v=v->next;
}
}
if(regsv[i]){
if(DEBUG&1) printf("Assigned <%s> to %s\n",regsv[i]->identifier,regnames[i]);
regsv[i]->priority=0;regused[i]=1;
if(regsv[i]->offset<0&&!(regsv[i]->flags&CONVPARAMETER)){
icp=(struct IC *)mymalloc(ICS);
icp->q1.am=icp->q2.am=icp->z.am=0;
icp->code=ASSIGN;
icp->typf=regsv[i]->vtyp->flags&31;
icp->q1.flags=VAR;
icp->q1.v=regsv[i];
icp->q1.val.vlong=l2zl(0L);
icp->q2.flags=0;
icp->q2.reg=szof(regsv[i]->vtyp);
icp->z.flags=REG;
icp->z.reg=i;
icp->next=first_ic;
icp->prev=0;
first_ic->prev=icp;
first_ic=icp;
}
icp=(struct IC *)mymalloc(ICS);
icp->q1.am=icp->q2.am=icp->z.am=0;
icp->code=ALLOCREG;
icp->q1.flags=REG;
icp->q1.reg=i;
icp->q2.flags=icp->z.flags=icp->typf=0;
icp->next=first_ic;
icp->prev=0;
first_ic->prev=icp;
first_ic=icp;
icp=(struct IC *)mymalloc(ICS);
icp->q1.am=icp->q2.am=icp->z.am=0;
icp->code=FREEREG;
icp->q1.flags=REG;
icp->q1.reg=i;
icp->q2.flags=icp->z.flags=icp->typf=0;
icp->next=0;
add_IC(icp);
}
}
icp=start;
while(icp){
if((icp->code==ALLOCREG||icp->code==FREEREG)&®sv[icp->q1.reg]){
/* irgendwelche allocreg/freereg im Code entfernen */
/* sollte nur beim Returnregister vorkommen */
struct IC *m=icp->next;
remove_IC(icp);
icp=m;continue;
}
for(i=1;i<=MAXR;i++){
if(!regsv[i]) continue;
if((icp->q1.flags&(VAR|DONTREGISTERIZE))==VAR&&icp->q1.v==regsv[i]){
icp->q1.flags|=REG;
icp->q1.reg=i;
}
if((icp->q2.flags&(VAR|DONTREGISTERIZE))==VAR&&icp->q2.v==regsv[i]){
icp->q2.flags|=REG;
icp->q2.reg=i;
}
if((icp->z.flags&(VAR|DONTREGISTERIZE))==VAR&&icp->z.v==regsv[i]){
icp->z.flags|=REG;
icp->z.reg=i;
}
}
icp=icp->next;
}
}